﻿/* ****************************************************************************
* Copyright (c) TCC - 2009 IME - USP. 
*
* This source code is subject to terms and conditions of the Microsoft Public License. 
* A copy of the license can be found in http://msdn.microsoft.com/en-us/library/dd228915.aspx. 
* By using this source code in any fashion, you are agreeing to be bound by the terms of the 
* Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
* ***************************************************************************/

namespace SoundLibrary.Converter
{
    public class BitStream
    {
        internal static sbyte INITIAL_SYNC = 0;
        internal static sbyte STRICT_SYNC = 1;
        private int wordpointer;
        private int bitindex;
        private int[] buffer;

        public BitStream(int bufferSize)
        {
            this.buffer = new int[bufferSize];
        }
        
        public void LoadBytes(sbyte[] frameBytes, int framesize)
        {
            int b = 0;
            sbyte[] byteread = frameBytes;
            int bytesize = framesize;

            for (int k = 0; k < bytesize; k = k + 4)
            {
                sbyte b0 = 0;
                sbyte b1 = 0;
                sbyte b2 = 0;
                sbyte b3 = 0;
                b0 = byteread[k];
                if (k + 1 < bytesize)
                {
                    b1 = byteread[k + 1];
                }
                if (k + 2 < bytesize)
                {
                    b2 = byteread[k + 2];
                }
                if (k + 3 < bytesize)
                {
                    b3 = byteread[k + 3];
                }

                this.buffer[b++] = (int)((b0 << 24) & 0xFF000000) | ((b1 << 16) & 0x00FF0000) | ((b2 << 8) & 0x0000FF00) | (b3 & 0x000000FF);
            }

            this.wordpointer = 0;
            this.bitindex = 0;
        }

        public int GetBits(int numberOfBits)
        {
            int returnvalue = 0;
            int sum = this.bitindex + numberOfBits;

            if (this.wordpointer < 0)
            {
                this.wordpointer = 0;
            }

            if (sum <= 32)
            {
                returnvalue = (this.buffer[this.wordpointer] >> (32 - sum)) & Util.BitMask[numberOfBits];
                if ((this.bitindex += numberOfBits) == 32)
                {
                    this.bitindex = 0;
                    this.wordpointer++;
                }
                return returnvalue;
            }

            int right = this.buffer[this.wordpointer++] & (int)Util.Identity(0x0000FFFF);
            int left = this.buffer[this.wordpointer] & (int)Util.Identity(0xFFFF0000);
            returnvalue = (right << 16) & (int)Util.Identity(0xFFFF0000) | (left >> 16) & (int)Util.Identity(0x0000FFFF);
            returnvalue = Util.URShift(returnvalue, 48 - sum) & Util.BitMask[numberOfBits];
            this.bitindex = sum - 32;
            return returnvalue;
        }
    }
}
